﻿using LxBasic;
using LxLESS;
using System.Collections.Generic;

namespace LxCore
{
    public abstract class WallDistanceSolver
    {
        public class Set : IInitialize/*: ConnectedZonesSolveSet<WallDisSolveSet,WallDisSolver, WallDistance,ConnectHeadBase>*/
        {
            public int MaxStep = 200;
            public void Initialize()
            {
                if (!isNeededGlobal()) return;
                var pools = new ConnectivitySolver().GetConnectivity<WallDistance, JointHead>(zf => zf.WallDistance, cf => null);//ConnectHeadBase这一项后面完善
                foreach (var p in pools)
                {
                    var solver = new Unit()
                    {
                        Equations = p.Equations.ToArray(),
                        Connects = p.Connects.ToArray(),
                        InSolveSet = this,
                    };
                    solver.Initialize();
                }
            }
            protected bool isNeededGlobal()
            {
                foreach (var zf in LxSim.Sim.Fields.ZoneFields)
                {
                    if (zf.WallDistance != null && !zf.WallDistance.IsInitialized)
                    {
                        return true;
                    }
                }
                return false;
            }
        }
        //1.需要考虑没有wall的情况，walldistance统一设置未最小允许壁面距离
        //2.考虑壁面处的cell value 为0，而不是bool类型标识
        public class Unit : IterateSolver.Unit /*: ConnectedZonesSolver<WallDisSolveSet, WallDistance, ConnectHeadBase>*/
        {
            public WallDistance[] Equations;
            public JointHead[] Connects;
            public Set InSolveSet;
            public override void Initialize()
            {
                if (isNeeded())
                {
                    var SolveEquations = new EquationWithTransTerm[Equations.Length];
                    var SolveConnects = new EquationConnectBase[Connects.Length];
                    for (int i1 = 0; i1 < Equations.Length; i1++)
                    {
                        SolveEquations[i1] = Equations[i1].MakePDECalulator();
                    }
                    calPDE(SolveEquations, SolveConnects);
                    MultiThreads.RunParallelTask((threadInfo) =>
                    {
                        for (int i1 = 0; i1 < Equations.Length; i1++)
                        {
                            Equations[i1].CalDistanceFromPDE(SolveEquations[i1], threadInfo);
                        }

                    });
                }
            }

            private bool isNeeded()
            {
                foreach (var walldis in Equations)
                {
                    if (!walldis.IsInitialized)
                    {
                        return true;
                    }
                }
                return false;
            }
            protected void calPDE(EquationWithTransTerm[] Equations, EquationConnectBase[] Connects)
            {
                Initialize(Equations);
                for (int step = 0; step < InSolveSet.MaxStep; step++)
                {
                    FormMatrix_SteadyPart(Equations, Connects);
                    Relax(Equations, Connects);
                    Solve(Equations, Connects);
                    UpdateBoundsValue(Equations, Connects);
                    Limit(Equations, Connects);
                    CalGradient(Equations, Connects);
                    CalResidual(Equations, Connects);

                    double res = 0;
                    foreach (var e in Equations)
                    {
                        var r = e.GetResidualReset();
                        if (r.res > res)
                        {
                            res = r.res;
                        }
                    }
                    if (res < 1e-5)
                    {
                        LxLog.Info("完成计算壁面距离。");
                        return;
                    }
                }
                LxLog.Error("计算壁面距离时未收敛！");
            }


        }
    }
   
}
//public List<WallDistance> DistanceZoneStore = new List<WallDistance>();
//public List<ConnectHeadBase> DistanceJointStore = new List<ConnectHeadBase>();
//public override void Rearrange(ConnectivitySolver connectivityAnalysis)
//{
//    Solvers = new List<DistanceUnit>();
//    var list = connectivityAnalysis.GetConnectivity(DistanceZoneStore, DistanceJointStore);
//    foreach (var l in list)
//    {
//        DistanceUnit u = new DistanceUnit();
//        u.CreateUnit(l.Zones, l.Joints);
//        Solvers.Add(u);
//    }
//    DistanceZoneStore.Clear();
//    DistanceJointStore.Clear();
//}